package com.eslag.rpc.handler;

import com.eslag.rpc.entity.RpcRequest;
import com.eslag.rpc.entity.RpcResponse;
import com.eslag.rpc.enumeration.ResponseCode;
import com.eslag.rpc.provider.ServiceProvider;
import com.eslag.rpc.provider.ServiceProviderImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 定义一个handler（处理器），供处理进行过程调用的请求参数
 */

public class RequestHandler {

    // 记录日志
    private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class);
    private static final ServiceProvider serviceProvider;
    /**
     * 处理RpcRequest请求
     * @param rpcRequest rpc请求参数
     * @param service Service对象
     * @return 返回调用方法返回的参数
     */
    static {
        serviceProvider = new ServiceProviderImpl();
    }

    public Object handle(RpcRequest rpcRequest) {
        // 从服务端本地注册表中获取服务实体
        Object service = serviceProvider.getServiceProvider(rpcRequest.getInterfaceName());

        return invokeTargetMethod(rpcRequest, service);
    }

    /**
     * 调用目标方法
     * @param rpcRequest 请求参数
     * @param service Service对象
     * @return 返回service段对应接口实现类方法返回值
     */
    private Object invokeTargetMethod(RpcRequest rpcRequest,Object service) {
        Object result;
        try {
            // getClass() 获取的是实例对象的类型
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
            result = method.invoke(service, rpcRequest.getParameters());
            logger.info("服务：{}成功调用方法：{}", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e){
            //方法调用失败
            return RpcResponse.fail(ResponseCode.METHOD_NOT_FOUND, rpcRequest.getRequestId());
        }
        //方法调用成功
        return RpcResponse.success(result, rpcRequest.getRequestId());
    }

}